package org.elsfs.cloud.common.mybatis.ext.sql;



import org.elsfs.cloud.common.mybatis.ext.sql.support.builder.StandardSelectSql;
import org.elsfs.cloud.common.mybatis.ext.sql.support.common.SimpleTableAliasManager;
import org.elsfs.cloud.common.mybatis.ext.sql.support.union.StandardUnionItem;
import org.elsfs.cloud.common.mybatis.ext.sql.support.union.UnionItem;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * 抽象的联合SQL实现
 *
 * @param <C> 子类具体实现
 */
@SuppressWarnings("unchecked")
public abstract class AbstractUnionSql<C extends AbstractUnionSql<C>> implements UnionSql<C>, SqlParameterManagerAware {

    /**
     * 具体子类实现引用
     */
    protected final C childThis = (C)  this;
    /**
     * 联合项列表
     */
    private final List<UnionItem> unionItems =  new ArrayList<>();

    /**
     * 联合（去重和排序）
     *
     * @param sqlBuilderConsumer SQL构建器消费器
     * @return 具体实现
     */
    @Override
    public C union(Consumer<StandardSelectSql> sqlBuilderConsumer) {
        StandardSelectSql standardSelectSql = new StandardSelectSql(this.getSqlParameterManager(), new SimpleTableAliasManager());
        sqlBuilderConsumer.accept(standardSelectSql);
        this.unionItems.add(
            new StandardUnionItem(standardSelectSql, UnionType.UNION)
        );

        return this.childThis;
    }

    /**
     * 粗暴联合
     *
     * @param sqlBuilderConsumer SQL构建器消费器
     * @return 具体实现
     */
    @Override
    public C unionAll(Consumer<StandardSelectSql> sqlBuilderConsumer) {
        StandardSelectSql standardSelectSql = new StandardSelectSql(this.getSqlParameterManager(), new SimpleTableAliasManager());
        sqlBuilderConsumer.accept(standardSelectSql);
        this.unionItems.add(
            new StandardUnionItem(standardSelectSql, UnionType.UNION_ALL)
        );

        return this.childThis;
    }

    /**
     * 构建SQL片段
     *
     * @return SQL片段
     */
    @Override
    public String buildSqlFragment() {
        if (this.unionItems.isEmpty()) {
            return "";
        }

        return UnionItem.stripHeaderKeyword(
            this.unionItems.stream()
                .map(SqlFragment::buildSqlFragment)
                .collect(Collectors.joining( " "))
        );
    }
}
